package com.hooview.api.service.impl;

import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.hooview.api.dao.*;
import com.hooview.api.entity.*;
import com.hooview.api.entity.dto.AuthorSimpleInfo;
import com.hooview.api.entity.dto.UserDTO;
import com.hooview.api.service.HyProfitService;
import com.hooview.api.service.UserService;
import com.hooview.contants.Constants;
import com.hooview.oauth2.TokenGenerator;
import com.hooview.utils.DateUtils;
import com.hooview.utils.SnowflakeIdWorker;
import org.apache.commons.lang3.RandomStringUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.crypto.hash.Sha256Hash;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.RequestBody;
import org.springside.modules.utils.number.RandomUtil;

import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.Map;

@Service
public class UserServiceImpl implements UserService {
    @Autowired
    private UserMapper userMapper;
    @Autowired
    private SnowflakeIdWorker snowflakeIdWorker;
    @Autowired
    private ProfitRecordMapper profitRecordMapper;
    @Autowired
    private NewsMapper newsMapper;
    @Autowired
    private FollowsMapper followsMapper;
    @Autowired
    private HyInputMapper hyInputMapper;
    @Autowired
    private HyProfitMapper hyProfitMapper;

    @Override
    public Sign queryObject(String id) {
        return null;
    }

    @Override
    public List<User> queryList(Map<String, Object> map) {
        return null;
    }

    @Override
    public void save(User user) {
    }

    @Override
    @Transactional(readOnly = false)
    public void update(@RequestBody User user) {
        user.setUpdateTime(new Date());
        userMapper.updateByPrimaryKeySelective(user);
    }

    @Override
    public void delete(String id) {

    }

    @Override
    @Transactional(readOnly = false)
    public void register(@RequestBody User user) {
        user.setId(getUUID());
        if (StringUtils.isNotBlank(user.getPassword())) {
            String salt = RandomStringUtils.randomAlphanumeric(20);
            user.setSalt(salt);
            user.setPassword(new Sha256Hash(user.getPassword(), salt).toHex());
        }

        String uid = RandomUtil.nextInt(100000, 999999) + "";
        if (StringUtils.isBlank(user.getDisplayName()))
            user.setDisplayName("火眼用户" + uid);
        user.setHyNum(uid);
        userMapper.insert(user);

        ProfitRecord profitRecord = new ProfitRecord();
        profitRecord.setNum(50d);
        profitRecord.setUid(user.getId());
        profitRecord.setType(Constants.PROFIT_REGISTER);
        profitRecord.setId(getUUID());
        profitRecordMapper.insertSelective(profitRecord);
    }

    @Override
    public User queryByUsername(String username) {
        return userMapper.queryByUsername(username);
    }

    @Override
    public User queryById(String uid) {
        return userMapper.selectByPrimaryKey(uid);
    }

    @Override
    @Transactional(readOnly = false)
    public String createToken(@RequestBody User user) {
        String token = null;
        while (true) {
            token = TokenGenerator.generateValue();
            User u = userMapper.queryByToken(token);
            if (u == null) break;
        }

        user.setToken(token);
        user.setLastSignTime(new Date());
        user.setUpdateTime(new Date());
        userMapper.updateByPrimaryKeySelective(user);
        return token;
    }

    @Override
    @Transactional(readOnly = false)
    public void logout(String token) {
        User user = userMapper.queryByToken(token);
        while (true) {
            token = TokenGenerator.generateValue();
            User u = userMapper.queryByToken(token);
            if (u == null) break;
        }
        user.setToken(token);
        user.setUpdateTime(new Date());
        userMapper.updateByPrimaryKeySelective(user);
    }

    @Override
    public User queryByOpenId(String openId) {
        return userMapper.queryByOpenId(openId);
    }

    @Override
    public Map queryByParams(@RequestBody Map<String, Object> params, Integer pageNum, Integer pageSize) {
        String formatDate = DateUtils.formatDate(new Date());
        params.put("createTime",formatDate);
        PageHelper.startPage(pageNum,pageSize,true,false);
        Page<UserDTO> page = userMapper.queryByParams(params);
        List<UserDTO> users = page.getResult();
        Map result = Maps.newHashMap();
        result.put("users",users);
        result.put("pageNum",page.getPageNum());
        result.put("total",page.getTotal());
        result.put("pages",page.getPages());
        return result;
    }

    @Override
    public Map queryMediaUserByParams(@RequestBody Map<String, Object> params, Integer pageNum, Integer pageSize) {
        PageHelper.startPage(pageNum,pageSize,true,false);
        Page<User> page = userMapper.queryMediaUserByParams(params);
        Map result = Maps.newHashMap();
        List<User> users = page.getResult();
        List<AuthorSimpleInfo> list = Lists.newArrayList();
        users.forEach(user -> {
            List<Map<String, Object>> news = newsMapper.findTop5ByReadAmount(user.getId());
            AuthorSimpleInfo authorSimpleInfo = new AuthorSimpleInfo(user);
            authorSimpleInfo.setNews(news);
            list.add(authorSimpleInfo);
        });
        result.put("total",page.getTotal());
        result.put("pages",page.getPages());
        result.put("pageNum",page.getPageNum());
        result.put("users",list);
        return result;
    }

    @Override
    public AuthorSimpleInfo queryAuthorInfo(String authorId) {
        User user = userMapper.queryAuthorInfo(authorId);
        AuthorSimpleInfo authorSimpleInfo = new AuthorSimpleInfo(user);
        Integer newsCount = newsMapper.countNewsByAuthor(authorId);
        Integer viewCount = newsMapper.sumReadAmountByAuthor(authorId);
        Integer fansCount = followsMapper.countFollowsByAuthor(authorId);
        authorSimpleInfo.setNewsCount(newsCount);
        authorSimpleInfo.setViewCount(viewCount);
        authorSimpleInfo.setFansCount(fansCount);
        return authorSimpleInfo;
    }

    @Override
    public List<User> findAll() {
        return userMapper.findAll();
    }

    @Override
    public Page<User> queryInvitedFriends(String uid, String type,Integer pageNum,Integer pageSize) {
        PageHelper.startPage(pageNum,pageSize,true);
        Page<User> page = userMapper.queryInvitedFriends(uid, type);
        if(pageNum > page.getPages())
            return null;
        return page;
    }

    @Override
    public Map<String, Object> queryTodayEnergyPoolInfo(String uid) {
        User user = userMapper.selectByPrimaryKey(uid);
        String today = DateUtils.formatDate(new Date());
        Calendar instance = Calendar.getInstance();
        instance.add(Calendar.DAY_OF_MONTH,-1);
        String yesterday = DateUtils.formatDate(instance.getTime());

        Float toalProfits = profitRecordMapper.todayToalProfits(today);
        HyInput todayHyInput = hyInputMapper.findByCreateTime(today);
        HyProfit hyProfit = hyProfitMapper.selectByTime(uid,yesterday);
        Float yesterHY = 0f;
        int i = (todayHyInput != null) ? todayHyInput.getRadix() : 0;
        if(hyProfit != null)
            yesterHY = hyProfit.getAmount();
        Map<String,Object> result = Maps.newHashMap();
        result.put("totalScore",toalProfits + i);
        result.put("totalHY",todayHyInput == null ? 0 :todayHyInput.getHy());
        result.put("yesterdayHY",yesterHY);
        result.put("userHy",user.getHyCoin());
        return result;
    }

    @Override
    public Integer countInvite(String uid) {
        return userMapper.countInvitat(uid);
    }

    @Override
    public Map recommendAuthor(@RequestBody Map<String, Object> params, Integer pageNum, Integer pageSize) {
        PageHelper.startPage(pageNum,pageSize,true,false);
        Page<User> page = userMapper.queryMediaUserByParams(params);
        Map result = Maps.newHashMap();
        List<User> users = page.getResult();
        List<AuthorSimpleInfo> list = Lists.newArrayList();
        users.forEach(user -> {
            List<Map<String, Object>> news = newsMapper.findTop5ByReadAmount(user.getId());
            if(news.size() >0){
                AuthorSimpleInfo authorSimpleInfo = new AuthorSimpleInfo(user);
                authorSimpleInfo.setNews(news);
                list.add(authorSimpleInfo);
            }
        });
        result.put("users",list);
        return result;
    }

    private String getUUID() {
        return String.valueOf(snowflakeIdWorker.nextId());
    }


}
